package com.dongfg.zcmserver.utils;

import com.alibaba.fastjson.JSON;
import com.dongfg.zcmserver.config.Config;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.List;

/**
 * base operation. Created by 13071472 on 2015/11/3.
 */
public class ZkUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(ZkUtils.class);

    public static boolean authrize(String path, String username, String securityKey) {
        ZooKeeper zooKeeper = ClientManager.getClient(Config.adminName, Config.adminPwd);
        List<ACL> acls = ACLHelper.buildACLs(username, securityKey);
        try {
            zooKeeper.create(path, JSON.toJSONString(new Date()).getBytes(), acls, CreateMode.PERSISTENT);
            return true;
        } catch (KeeperException e) {
            LOGGER.error("KeeperException", e);
        } catch (InterruptedException e) {
            LOGGER.error("KeeperException", e);
        }
        return false;
    }

    /**
     * create node with data and acls.
     *
     * @param zooKeeper zk client.
     * @param acls      acl list.
     * @param path      node path.
     * @param data      node data.
     * @return return true if create success or node exists,otherwise return false.
     */
    public static boolean create(ZooKeeper zooKeeper, List<ACL> acls, String path, byte[] data) {
        try {
            zooKeeper.create(path, data, acls, CreateMode.PERSISTENT);
            return true;
        } catch (KeeperException.NodeExistsException e) {
            return true;
        } catch (KeeperException.NoAuthException e) {
            LOGGER.error("NoAuthException", e);
        } catch (KeeperException e) {
            LOGGER.error("KeeperException", e);
        } catch (InterruptedException e) {
            LOGGER.error("InterruptedException", e);
        }
        return false;
    }

    /**
     * read node value.
     *
     * @param zooKeeper zk client.
     * @param path      node path.
     * @return return real value if success otherwise new byte[0](May not be proper)
     */
    public static byte[] read(ZooKeeper zooKeeper, String path) {
        try {
            return zooKeeper.getData(path, false, null);
        } catch (KeeperException e) {
            LOGGER.error("KeeperException", e);
        } catch (InterruptedException e) {
            LOGGER.error("InterruptedException", e);
        }
        return new byte[0];
    }

    public static boolean update(ZooKeeper zooKeeper, String path, byte[] data) {
        try {
            zooKeeper.setData(path, data, -1);
            return true;
        } catch (KeeperException e) {
            LOGGER.error("KeeperException", e);
        } catch (InterruptedException e) {
            LOGGER.error("InterruptedException", e);
        }
        return false;
    }

    public static boolean delete(ZooKeeper zooKeeper, String username, String path) {
        try {
            Stat stat = zooKeeper.exists(path, false);
            if (stat != null) {
                List<ACL> acls = zooKeeper.getACL(path, stat);
                boolean hasAuth = false;
                for (ACL acl : acls) {
                    if (acl.getId().getId().startsWith(username)) {
                        hasAuth = true;
                    }
                }
                if (hasAuth) {
                    ZooKeeper adminClient = ClientManager.getClient("admin", "admin");
                    adminClient.delete(path, -1);
                    return true;
                }
            }
        } catch (KeeperException e) {
            LOGGER.error("KeeperException", e);
        } catch (InterruptedException e) {
            LOGGER.error("InterruptedException", e);
        }
        return false;
    }
}
